﻿using System;
using System.Drawing;
using System.Linq;
using RRRSRoguelike.Entities.Creatures;
using RRRSRoguelike.Enums;
using RRRSRoguelikeData;

namespace RRRSRoguelike.Entities
{
	/// <summary>
	/// A tile is a basic building block of the game.  Each section of the map
	/// is a tile.
	/// </summary>
	public class Tile
	{
		#region variables
		/// <summary>
		/// Shows whether the Tile is active and updating
		/// </summary>
		public bool Active;
		/// <summary>
		/// Holds the data for the tile
		/// </summary>
		protected TileData TileData = new TileData();
		#endregion
		#region properties

		/// <summary>
		/// The XY position of this tile
		/// </summary>
		public Point Position
		{
			get { return new Point(TileData.X, TileData.Y); }
			set { TileData.X = value.X; TileData.Y = value.Y; }
		}
		/// <summary>
		/// Can this tile be walked through
		/// </summary>
		public bool Walkable
		{
			get { return TileData.Walkable; }
			set { TileData.Walkable = value; }

		}

		/// <summary>
		/// X position
		/// </summary>
		public int X
		{
			get { return (TileData.X); }
			set { TileData.X = value; }
		}

		/// <summary>
		/// Y position
		/// </summary>
		public int Y
		{
			get { return (TileData.Y); }
			set { TileData.Y = value; }
		}

		/// <summary>
		/// Holds the console color
		/// </summary>
		public ConsoleColor Color
		{
			get { return Constants.ColorsDictionary[TileData.ForeColor]; }
			set { TileData.ForeColor = Constants.ColorsDictionary.FirstOrDefault(x => x.Value == value).Key; }
		}
		/// <summary>
		/// Holds the bckgound color
		/// </summary>
		public ConsoleColor Background
		{
			get { return Constants.ColorsDictionary[TileData.BackColor]; }
			set { TileData.BackColor = Constants.ColorsDictionary.FirstOrDefault(x => x.Value == value).Key; }
		}
		/// <summary>
		/// holds the image character
		/// </summary>
		public string ImageCharacter
		{
			get { return (TileData.ImageCharacter); }
			set { TileData.ImageCharacter = value; }
		}
		
		/// <summary>
		/// Holds the dscription of the tile
		/// </summary>
		public string Description
		{
			get { return (TileData.Description); }
			set { TileData.Description = value; }
		}

		/// <summary>
		/// Holds the name of the tile
		/// </summary>
		public string Name
		{
			get { return (TileData.Name); }
			set { TileData.Name = value; }
		}

		#endregion
		#region constructors
		
		/// <summary>
		/// Constructor
		/// </summary>
		public Tile()
		{
			Initialize(0, 0);
		}
		
		/// <summary>
		/// constructor with x,y
		/// </summary>
		/// <param name="x"></param>
		/// <param name="y"></param>
		public Tile(int x, int y)
		{
			Initialize(x, y);
		}

		/// <summary>
		/// Constructor with point
		/// </summary>
		/// <param name="point"></param>
		public Tile(Point point)
		{
			Initialize(point.X, point.Y);
		}

		/// <summary>
		/// Constructor with point and tileData
		/// </summary>
		/// <param name="point"></param>
		/// <param name="tileData"></param>
		public Tile(Point point, TileData tileData)
		{

			TileData = (TileData)tileData.Clone();
			X = point.X;
			Y = point.Y;
		}
		
		/// <summary>
		/// constructor
		/// </summary>
		/// <param name="imageCharacter"></param>
		/// <param name="color"></param>
		/// <param name="position"></param>
		public Tile(string imageCharacter, ConsoleColor color, Point position)
		{
			ImageCharacter = imageCharacter;
			Color = color;
			Background = ConsoleColor.Black;
			Position = position;
			Active = true;
		}


		#endregion
		
		#region methods

		/// <summary>
		/// Initializes tile.
		/// </summary>
		/// <param name="x"></param>
		/// <param name="y"></param>
		private void Initialize(int x, int y)
		{
			X = x;
			Y = y;
			ImageCharacter = "";
			Color = Constants.ColorsDictionary["White"];
			Description = "See Me!";
		}

		/// <summary>
		/// Move tile in direction for distance.
		/// </summary>
		/// <param name="point"></param>
		/// <param name="direction"></param>
		/// <param name="distance"></param>
		public void Move(Point point, Direction direction, int distance)
		{

			switch (direction)
			{
				case Direction.N:
					TileData.Y -= distance;
					break;
				case Direction.S:
					TileData.Y += distance;
					break;
				case Direction.E:
					TileData.X += distance;
					break;
				case Direction.W:
					TileData.X -= distance;
					break;
			}
		}

		/// <summary>
		/// Cause tile to kill creature
		/// </summary>
		/// <param name="creature"></param>
		public void KillCreature(Creature creature)
		{
			creature.Hits = 0;
		}

		/// <summary>
		/// Compares tiles according to appearance but not description.
		/// </summary>
		/// <param name="tile"></param>
		/// <returns></returns>
		public bool IsVisuallySimilar(Tile tile)
		{
			if (tile != null)
			{
				if (Color == tile.Color && ImageCharacter == tile.ImageCharacter)
					return true;
			}
			else
			{
				return true;
			}
			return false;

		}
		#endregion
	}
}
